package com.duobaoyu.dby.supply.biz.strategy.message.order.split;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.duobaoyu.dby.channel.adapter.enums.BizMessageTypeEnum;
import com.duobaoyu.dby.channel.adapter.enums.ChannelCodeEnum;
import com.duobaoyu.dby.channel.boundary.bean.order.param.OrderInfoParam;
import com.duobaoyu.dby.channel.boundary.bean.order.result.OrderInfoResult;
import com.duobaoyu.dby.channel.boundary.template.SupplyChannelTemplate;
import com.duobaoyu.dby.common.core.constant.CommonConstants;
import com.duobaoyu.dby.common.mybatis.config.IdGeneratorSnowflake;
import com.duobaoyu.dby.common.mybatis.util.EnumUtils;
import com.duobaoyu.dby.supply.biz.enums.OrderLevelEnum;
import com.duobaoyu.dby.supply.biz.enums.OrderParentTypeEnum;
import com.duobaoyu.dby.supply.biz.producer.SupplyChainMQProducer;
import com.duobaoyu.dby.supply.biz.strategy.message.order.base.BaseOrderAsyncHandler;
import com.duobaoyu.dby.supply.common.biz.bo.message.ChannelMessageBO;
import com.duobaoyu.dby.supply.db.entity.order.Order;
import com.duobaoyu.dby.supply.db.entity.order.OrderConsignee;
import com.duobaoyu.dby.supply.db.entity.order.OrderProduct;
import com.duobaoyu.dby.supply.db.repository.order.OrderConsigneeRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderProductRepository;
import com.duobaoyu.dby.supply.db.repository.order.OrderRepository;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 京东拆单
 *
 * @author fengshaoyu
 * @version 1.0.0
 * @date 2023/10/21 10:43
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class JdVopSplitOrderInfoAsyncHandler extends BaseOrderAsyncHandler {

	private final OrderRepository orderRepository;
	private final TransactionTemplate transactionTemplate;
	private final IdGeneratorSnowflake idGeneratorSnowflake;
	private final SupplyChannelTemplate supplyChannelTemplate;
	private final OrderProductRepository orderProductRepository;
	private final SupplyChainMQProducer supplyChainMQProducer;
	private final OrderConsigneeRepository orderConsigneeRepository;

	@Override
	protected Set<String> channelCodes() {
		return Sets.newHashSet(ChannelCodeEnum.JD_VOP.getValue());
	}

	@Override
	protected Set<Integer> bizMessageTypes() {
		return Sets.newHashSet(BizMessageTypeEnum.ORDER_SPLIT.getValue());
	}

	@Override
	protected Boolean executeHandler(ChannelMessageBO channelMessage, Object beforeResult) {
		List<Order> orderList = this.getOrderList(channelMessage);
		if (ObjectUtils.isEmpty(orderList)) {
			return Boolean.FALSE;
		}

		transactionTemplate.execute(new TransactionCallbackWithoutResult() {
			@Override
			protected void doInTransactionWithoutResult(@NotNull TransactionStatus transactionStatus) {
				List<Order> orderSaveList = Lists.newArrayList();
				List<OrderProduct> orderProductCopyList = Lists.newArrayList();
				List<OrderConsignee> orderConsigneeList = Lists.newArrayList();
				//-1 为订单祖节点
				List<Order> orders = orderList.stream().filter(item -> EnumUtils.eq(OrderLevelEnum.CHANNEL_MASTER_ORDER, item.getOrderParentSn())).collect(Collectors.toList());
				for (Order order : orders) {
					List<OrderProduct> orderProductList = orderProductRepository.list(Wrappers.<OrderProduct>lambdaQuery().eq(OrderProduct::getOrderSn, order.getOrderSn()));
					OrderConsignee orderConsignee = orderConsigneeRepository.getOne(Wrappers.<OrderConsignee>lambdaQuery().eq(OrderConsignee::getOrderSn, order.getOrderSn()));

					OrderInfoParam orderInfoParam = new OrderInfoParam();
					orderInfoParam.setChannelCode(channelMessage.getChannelCode());
					orderInfoParam.setChannelOrderSn(order.getChannelOrderSn());
					orderInfoParam.setOrderTradeSn(order.getOrderTradeSn());
					OrderInfoResult orderInfo = supplyChannelTemplate.getOrderInfo(orderInfoParam);

					List<OrderInfoResult.RealOrderDetail> realOrderDetailList = orderInfo.getRealOrderDetailList().stream().filter(realOrderDetail -> Objects.equals(realOrderDetail.getParentType(), CommonConstants.ZERO)).collect(Collectors.toList());

					orderRepository.update(Wrappers.<Order>lambdaUpdate()
							.eq(Order::getParentType, OrderParentTypeEnum.BEFORE_SPLIT.getValue())
							.eq(Order::getSupplyTradeSn, order.getSupplyTradeSn()));

					for (OrderInfoResult.RealOrderDetail orderDetail : realOrderDetailList) {

						List<OrderProduct> orderProductNewList = Lists.newArrayList();
						for (OrderInfoResult.RealOrderDetail.RealOrderSkuInfo skuInfo : orderDetail.getSkuInfos()) {
							for (OrderProduct orderProduct : orderProductList) {
								if (Objects.equals(skuInfo.getChannelSkuCode(), orderProduct.getChannelSkuCode())) {
									OrderProduct clone = orderProduct.clone();
									clone.setSkuNum(skuInfo.getSkuNum());
									orderProductNewList.add(clone);
								}
							}
						}

						reckon(orderProductNewList);

						Order orderNew = createOrder(order.clone(), orderProductNewList);
						orderNew.setChannelOrderParentSn(order.getChannelTradeOrderSn());
						orderNew.setChannelOrderSn(orderDetail.getChannelOrderSn());
						orderProductNewList.forEach(item -> item.setOrderSn(orderNew.getOrderSn()));

						OrderConsignee clone = orderConsignee.clone();
						clone.setId(idGeneratorSnowflake.snowflakeId());
						clone.setOrderSn(orderNew.getOrderSn());

						orderSaveList.add(orderNew);
						orderProductCopyList.addAll(orderProductNewList);
						orderConsigneeList.add(clone);
					}
					supplyChainMQProducer.orderAlterSend(order.getSupplyTradeSn(), order.getServerName());
				}

				orderRepository.saveBatch(orderSaveList);
				orderProductRepository.saveBatch(orderProductCopyList);
				orderConsigneeRepository.saveBatch(orderConsigneeList);
			}
		});
		return Boolean.TRUE;
	}
}
